PM-31920 adding the whole report endpoints v2#7079
PM-31920 adding the whole report endpoints v2#7079prograhamming wants to merge 11 commits intomainfrom
Conversation
|
Fixed Issues (4)Great job! The following issues were fixed in this Pull Request
|
…-access-intelligence
…-access-intelligence
…elligence' of github.com:bitwarden/server into dirt/pm-31920-whole-report-data-v2-endpoints-access-intelligence
…-access-intelligence
…elligence' of github.com:bitwarden/server into dirt/pm-31920-whole-report-data-v2-endpoints-access-intelligence
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #7079 +/- ##
===========================================
- Coverage 56.45% 13.82% -42.64%
===========================================
Files 2013 1246 -767
Lines 88098 52938 -35160
Branches 7860 4089 -3771
===========================================
- Hits 49739 7318 -42421
- Misses 36543 45488 +8945
+ Partials 1816 132 -1684 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…-access-intelligence
…-access-intelligence
|
|
@claude review this pr |
|
Claude finished @prograhamming's task in 4m 44s —— View job Review of PR #7079 — PM-31920 V2 Report Endpoints
SummaryThis PR adds V2 endpoints for organization report CRUD operations behind the Security Issues1. Path Traversal in
|
| private static string RelativePath(OrganizationReport report, string fileId, string fileName) | ||
| { | ||
| var date = report.CreationDate.ToString("MM-dd-yyyy"); | ||
| return Path.Combine(report.OrganizationId.ToString(), date, report.Id.ToString(), | ||
| fileId, fileName); | ||
| } |
There was a problem hiding this comment.
Path Traversal (Medium): The fileId parameter flows directly into Path.Combine without sanitization. While the create flow generates safe IDs via CoreHelpers.SecureRandomString, defense in depth should validate the resolved path stays under _baseDirPath. The test at LocalOrganizationReportStorageServiceTests:103 explicitly demonstrates this vulnerability works with ../../ payloads.
Consider adding validation after path construction:
| private static string RelativePath(OrganizationReport report, string fileId, string fileName) | |
| { | |
| var date = report.CreationDate.ToString("MM-dd-yyyy"); | |
| return Path.Combine(report.OrganizationId.ToString(), date, report.Id.ToString(), | |
| fileId, fileName); | |
| } | |
| private static string RelativePath(OrganizationReport report, string fileId, string fileName) | |
| { | |
| var date = report.CreationDate.ToString("MM-dd-yyyy"); | |
| return Path.Combine(report.OrganizationId.ToString(), date, report.Id.ToString(), | |
| fileId, fileName); | |
| } |
Alternatively, add a path traversal guard in WriteFileAsync and ValidateFileAsync:
var fullPath = Path.GetFullPath(path);
if (!fullPath.StartsWith(Path.GetFullPath(_baseDirPath)))
throw new InvalidOperationException("Invalid file path");| private readonly IOrganizationReportStorageService _storageService; | ||
| private readonly ICreateOrganizationReportV2Command _createV2Command; | ||
| private readonly IUpdateOrganizationReportDataV2Command _updateDataV2Command; | ||
| private readonly IGetOrganizationReportDataV2Query _getDataV2Query; |
There was a problem hiding this comment.
Bug: _getDataV2Query is injected but never called anywhere in this controller or the codebase. The GetOrganizationReportDataAsync GET endpoint (line 263) has no V2 feature-flag branch, so there's no way for clients to retrieve a download URL for V2 report data files.
This appears to be a missing V2 read endpoint — should the GET at line 263 have a WholeReportDataFileStorage branch that calls _getDataV2Query.GetOrganizationReportDataAsync() (similar to how create/update endpoints have V2 branches)?
| public int? CriticalPasswordCount { get; set; } | ||
| public int? CriticalPasswordAtRiskCount { get; set; } | ||
| public string? ReportFile { get; set; } | ||
| public ReportFile? OrganizationReportFile { get; set; } |
There was a problem hiding this comment.
Unused property: OrganizationReportFile is never accessed anywhere in the codebase. File data is stored/retrieved via GetReportFileData()/SetReportFileData() which serialize to/from the ReportData string. If this isn't mapped to a DB column, it should be removed to avoid confusion.





🎟️ Tracking
This is a PR for a sub-task (PM-32520) on user story PM-31923
📔 Objective
Creating new V2 endpoints for read and update operations on the whole report in the database. This will also include the logic for saving a reportData file in Azure Blob storage and server if self-hosted.
📸 Screenshots